﻿using System.Linq;
using System.Text;
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using Scurvy;
using Scurvy.Media;
using Scurvy.Media.VideoModel;
using Scurvy.Media.Audio;

namespace TheGame
{

    //Classe per la gestione di un livello
    //[p.54,55]
    public class Level
    {
        Game1 game;
        public string NAME;
        public int difficult = 0;
        public string Enviorement = "";

        public Texture2D BackGround;
        public Texture2D BackGround_DEBUG;

        public Level NextRIGHT;
        public Level NextLEFT;
        public Level NextUP;
        public Level NextDOWN;

        public bool Sentinella = false;     
        public List<Mudokon> Mudokons;
        public List<Slig> Sligs;
        public List<ObjectA> ObjectsA;
        public List<Video> VIDEOS;
        public List<Rectangle> VIDEOSREC;
        public Texture2D OBJECTS;

        public bool FLOOR2NDLeft = false;
        public bool FLOOR2NDRight = false;
        public bool BLOCCOUPRight = false;
        public bool BLOCCOUPLeft = false;
        public bool BLOCCODOWNRight = false;
        public bool BLOCCODOWNLeft = false;

        //Livelli strutturalmente compatibili
        public List<Level> compatibleLevels = new List<Level>();

        //Struttura architettonica[p.55]
        public List<List<Collision>> COLLISIONGROUPS = new List<List<Collision>>();

        public Level(Level levelCopy)
        {
            this.game = levelCopy.game;
            this.NAME = levelCopy.NAME;
            this.Enviorement = levelCopy.Enviorement;
            this.BackGround = levelCopy.BackGround;
            this.BackGround_DEBUG = levelCopy.BackGround_DEBUG;

            this.FLOOR2NDLeft = levelCopy.FLOOR2NDLeft;
            this.FLOOR2NDRight = levelCopy.FLOOR2NDRight;

            this.BLOCCOUPLeft = levelCopy.BLOCCOUPLeft;
            this.BLOCCOUPRight = levelCopy.BLOCCOUPRight;
            this.BLOCCODOWNRight = levelCopy.BLOCCODOWNRight;
            this.BLOCCODOWNLeft = levelCopy.BLOCCODOWNLeft;

            this.Sentinella = levelCopy.Sentinella;

            this.OBJECTS = levelCopy.OBJECTS;

            this.difficult = levelCopy.difficult;

            Mudokons = new List<Mudokon>();
            foreach (Mudokon mud in levelCopy.Mudokons)
            {
                Mudokon mud2 = new Mudokon(game, mud.AI.CURRENT_STATE.name, mud.BoundigBox.Location);
                this.AddMudokon(mud2);
            }
            Sligs = new List<Slig>();
            foreach (Slig slig in levelCopy.Sligs)
            {
                Slig slig2 = new Slig(game, slig.AI.CURRENT_STATE.name, slig.AI_LEVEL, slig.position);
                slig2.levelDefault = this;
                this.AddSlig(slig2);
            }

            ObjectsA = new List<ObjectA>();
            foreach (ObjectA objA in levelCopy.ObjectsA)
            {

                foreach (ObjectA slave in objA.SLAVES)
                {
                    slave.LEVEL = this;
                }
              
                objA.LEVEL = this;
                this.ObjectsA.Add(objA);
            }
            COLLISIONGROUPS = levelCopy.COLLISIONGROUPS;

            VIDEOS = levelCopy.VIDEOS;
            VIDEOSREC = levelCopy.VIDEOSREC;           
        }

        public Level(string Env, Game1 game)
        {
            this.Enviorement = Env;
            this.game = game;
            Mudokons = new List<Mudokon>();
            Sligs = new List<Slig>();

            ObjectsA = new List<ObjectA>();
            VIDEOS = new List<Video>();
            VIDEOSREC = new List<Rectangle>();

            BackGround = game.Content.Load<Texture2D>("LVL\\BackGround\\" + Enviorement);
            
            try{
                //BackGround_DEBUG = game.Content.Load<Texture2D>("LVL\\Debug\\" + Enviorement + "_DEBUG");
                OBJECTS = game.Content.Load<Texture2D>("LVL\\OBJECTS\\" + Enviorement);
            }catch(Exception e){}
        }

        
      
        public List<string> collision(Rectangle recToTest)
        {
            List<string> collisions = new List<string>();

            for (int i = 0; i < COLLISIONGROUPS.Count; i++)
            {
                foreach (Collision coll in COLLISIONGROUPS[i])
                {
                    if (recToTest.Intersects(coll.REC))
                        collisions.Add(coll.TYPE);
                }
            }
            return collisions;
        }

        //Dato un qualsiasi personaggio (Abe,Mudokon o Slig) restituisce una lista contenente
        //tutti gli elementi che collidono con la sua BoundingBox
        public List<string> collision(Character chracter)
        {
            List<string> collisions = new List<string>();
            chracter.CURRENTOBJECTA = null;

            for (int i = 0; i < COLLISIONGROUPS.Count; i++)
            {
                switch (COLLISIONGROUPS[i][0].TYPE)
                {
                    case COLLISIONS.BLOCCO:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC) & IsNearFrontBlocco(chracter.boundingBox,coll.REC, chracter.Direction))
                            {
                                collisions.Add(COLLISIONS.BLOCCO);
                            }
                        }
                        break;

                    case COLLISIONS.LEVA:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC) & IsNearObj(chracter.boundingBox, coll.REC, chracter.Direction))
                            {
                                collisions.Add(coll.TYPE);
                                chracter.CURRENTOBJECTA = coll.OBJA;
                            }
                        }
                        break;

                    case COLLISIONS.BOMBINNESCO:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC) && IsNearObj(chracter.boundingBox, coll.REC, chracter.Direction))
                            {
                                collisions.Add(COLLISIONS.BOMBINNESCO);
                                chracter.CURRENTOBJECTA = coll.OBJA;                                                               
                            }
                            if (chracter.boundingBox.Intersects(coll.REC) && IsOnObj(chracter.boundingBox, coll.REC)) 
                            {
                                chracter.CURRENTOBJECTA = coll.OBJA;
                                if(chracter.CURRENTOBJECTA != null && chracter.CURRENTOBJECTA.objControl.ACTIVE)
                                    collisions.Add(COLLISIONS.BOMB);
                            }                               
                        }
                        break;

                    case COLLISIONS.PORTAL:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC))
                            {
                                chracter.CURRENTOBJECTA = coll.OBJA;
                                collisions.Add(coll.TYPE);
                            }
                        }
                        break;

                    default:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC))
                                collisions.Add(coll.TYPE);
                        }
                        break;
                }              
            }
            return collisions;
        }

        public List<Collision> GetCollision(Character chracter)
        {
            List<Collision> collisions = new List<Collision>();
            chracter.CURRENTOBJECTA = null;

            for (int i = 0; i < COLLISIONGROUPS.Count; i++)
            {
                switch (COLLISIONGROUPS[i][0].TYPE)
                {

                    case COLLISIONS.BLOCCO:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC) & IsNearFrontBlocco(chracter.boundingBox, coll.REC, chracter.Direction))
                            {
                                collisions.Add(coll);
                            }

                        }
                        break;

                    case COLLISIONS.LEVA:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC) & IsNearObj(chracter.boundingBox, coll.REC, chracter.Direction))
                            {
                                collisions.Add(coll);
                                chracter.CURRENTOBJECTA = coll.OBJA;
                            }

                        }
                        break;

                    case COLLISIONS.BOMBINNESCO:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC) && IsNearObj(chracter.boundingBox, coll.REC, chracter.Direction))
                            {
                                collisions.Add(coll);
                                chracter.CURRENTOBJECTA = coll.OBJA;
                                if (chracter.CURRENTOBJECTA != null && chracter.CURRENTOBJECTA.objControl.ACTIVE)
                                    collisions.Add(coll);
                            }

                        }
                        break;

                    case COLLISIONS.PORTAL:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC))
                            {
                                chracter.CURRENTOBJECTA = coll.OBJA;
                                collisions.Add(coll);
                            }
                        }
                        break;

                    default:
                        foreach (Collision coll in COLLISIONGROUPS[i])
                        {
                            if (chracter.boundingBox.Intersects(coll.REC))
                                collisions.Add(coll);
                        }
                        break;
                }

            }

            return collisions;

        }

        bool IsOnObj(Rectangle Chara, Rectangle Obj)
        {
            int Diff1 =  Chara.X - Obj.X;
            int Diff2 = Obj.Right - Chara.Right;

            if (Diff1 < 10 & Diff2 < 15)
                return true;
            else
                return false;
        }

        bool IsNearObj(Rectangle Chara, Rectangle Obj, int Direction)
        {
            int Diff1 = Chara.Right - Obj.X;
            int Diff2 = Obj.Right - Chara.X;

            if ((Direction == 1 & Diff1 <= 10 & Diff1 >= 0) || (Direction == -1 & Diff2 <= 10 & Diff2 >= 0))
                return true;
            else
                return false;
        }

        bool IsNearFrontBlocco(Rectangle Chara, Rectangle Blocco, int Direction)
        {
            int DiffLeft = Blocco.Right - Chara.X;
            int DiffRight = Chara.Right - Blocco.X;

            if (DiffLeft >= 0 & DiffLeft <= 10 & Direction == -1 || DiffRight >= 0 & DiffRight <= 10 & Direction == 1)
                return true;
            else
                return false;
        }        

        public void AddObject(Texture2D obj)
        {
            OBJECTS = obj;
        }

        public void AddObjectA(ObjectA objA)
        {
            ObjectsA.Add(objA);
        }

        public void RemoveObjectA(ObjectA objA)
        {
            RemoveCOLLISION(objA.COLLISION);
            ObjectsA.Remove(objA);
        }

        public void AddVideo(Video vid, Rectangle vidRec)
        {
            VIDEOS.Add(vid);
            VIDEOSREC.Add(vidRec);
        }

        public void AddMudokon(Mudokon MUD)
        {
            Mudokons.Add(MUD);
            MUD.CurrentLevel = this;
        }

        public void RemoveMudokon(Mudokon MUD)
        {
            Mudokons.Remove(MUD);
        }

        public void AddSlig(Slig SLIG)
        {
            Sligs.Add(SLIG);
            SLIG.CurrentLevel = this;
        }

        public void RemoveSlig(Slig SLIG)
        {
            Sligs.Remove(SLIG);
        }

        public void AddCOLLISION(Collision CollToAdd)
        {
            bool exist = false;

            for(int i = 0; i < COLLISIONGROUPS.Count; i++)
            {

                if (COLLISIONGROUPS[i][0].TYPE == CollToAdd.TYPE)
                {
                    COLLISIONGROUPS[i].Add(CollToAdd);
                    exist = true;
                }
                 
            }

            if(!exist)
            {
                List<Collision> newGroup = new List<Collision>();
                newGroup.Add(CollToAdd);
                COLLISIONGROUPS.Add(newGroup);
            }
                
        }

        public void RemoveCOLLISION(Collision CollToRemove)
        {
            for (int i = 0; i < COLLISIONGROUPS.Count; i++)
            {
                if (COLLISIONGROUPS[i][0].TYPE == CollToRemove.TYPE)
                {

                    COLLISIONGROUPS[i].Remove(CollToRemove);
                }

                if (COLLISIONGROUPS[i].Count == 0)
                    COLLISIONGROUPS.Remove(COLLISIONGROUPS[i]);

            }
        }

        public void RESET()
        {
            for (int i = 0; i < ObjectsA.Count; i++)
                ObjectsA[i].objControl.RESET();

            for (int i = 0; i < Sligs.Count; i++)
            {
                Sligs[i].AI.CURRENT_STATE.RESET();
                if (this != Sligs[i].levelDefault)
                    this.RemoveSlig(Sligs[i]);
            }
        }

        //Metodo che riadatta la difficoltà del livello
        //Chiamato nella classe Report 
        public void Modify(string Code)
        {
            if (Code == "DIFF_UP")
            {
                SetUPSlig();
                SetUPBomb();
                SetUPBombInnesco();
            }
            if (Code == "DIFF_DOWN")
            {
                SetDOWNSLIG();
                SetDOWNBomb();
            }
            NextRIGHT = null;
            NextLEFT = null;
            NextUP = null;
            NextDOWN = null;
        }

        //Incrementa la difficoltà del livello agendo sui nemici
        public void SetUPSlig()
        {
            bool bombs = false;
            foreach (ObjectA obj in ObjectsA)
            {
                if (obj.NAME == "BOMBS" & obj.COLLISION.REC.Y == 385)
                    bombs = true;
            }


            //Se il livello continene nemici
            //Ai nemici già presenti nel livello viene aumentato il fattore IA
            //Viene aggiunto un nemico(Slig) con IA minima
            //Viene aggiunta una Sentinella(classe ObjectA)
            if (Sligs.Count > 0)
            {
                bool AllAiMax = false;
                if ((FLOOR2NDLeft || FLOOR2NDRight) & !Sentinella)
                {
                    Sentinella = true;
                    ObjectA OMM = new ObjectA(game, "OMM", new Rectangle(500, 50, 0, 0), new Collision(COLLISIONS.SHOCK, new Rectangle()), this);
                    this.AddObjectA(OMM);
                }

                foreach (Slig slig in Sligs)
                {
                    if (slig.AI_LEVEL == 4)
                        AllAiMax = true;
                    else
                        AllAiMax = false;
                }
                if (AllAiMax & Sligs.Count < 2)
                {
                    if (!bombs)
                    {
                        Rectangle Spawn = new Rectangle(49 + 43 * 3, 395, 44, 50);
                        Slig slig;
                        if (Sligs[0].state == "SLEEP")
                            slig = new Slig(game, "SENTINELLA", 2, Spawn.Location);
                        else
                            slig = new Slig(game, "SLEEP", 2, Spawn.Location);

                        List<string> ColTypes = this.collision(slig);
                        int blocchi = 0;
                        for (int i = Spawn.Location.X; i <= 522; i += 43)
                        {
                            ColTypes = this.collision(slig);
                            if (ColTypes.Count == 0)
                            {
                                slig.levelDefault = this;
                                this.AddSlig(slig);
                                i = 1000;
                            }
                            if (ColTypes.Contains(COLLISIONS.BLOCCO))
                                blocchi++;
                            if (!ColTypes.Contains(COLLISIONS.BLOCCO) & blocchi > 0)
                                blocchi--;

                            if (blocchi > 3)
                                i = 1000;
                        }
                    }
                }
                foreach (Slig slig in Sligs)
                {
                    if (slig.AI_LEVEL < 4)
                        slig.AI_LEVEL++;
                }
                foreach (Slig slig in Sligs)
                {
                    if (slig.AI_LEVEL < 4)
                        slig.AI_LEVEL++;
                }
            }

            //Se il livello non continene nemici
            //Viene aggiunto un nemico(Slig) con IA media
            else
            {
                if (!bombs)
                {
                    Rectangle Spawn = new Rectangle(49, 395, 44, 50);
                    Slig slig = new Slig(game, "SENTINELLA", 2, Spawn.Location);
                    List<string> ColTypes = this.collision(slig);
                    int blocchi = 0;

                    for (int i = Spawn.Location.X; i <= 522; i += 43)
                    {
                        ColTypes = this.collision(slig);
                        if (ColTypes.Count == 0)
                        {
                            slig.levelDefault = this;
                            this.AddSlig(slig);
                            i = 1000;
                        }
                        if (ColTypes.Contains(COLLISIONS.BLOCCO))
                            blocchi++;
                        if (!ColTypes.Contains(COLLISIONS.BLOCCO) & blocchi > 0)
                            blocchi--;

                        if (blocchi > 3)
                            i = 1000;
                    }
                }
            }
        }

        //Decrementa la difficoltà del livello agendo sui nemici
        public void SetDOWNSLIG()
        {
            int totalAI = 0;
            if (Sligs.Count > 0)
            {
                Sentinella = false;
                for (int i = 0; i < ObjectsA.Count; i++)
                    if (ObjectsA[i].NAME == "OMM")
                        RemoveObjectA(ObjectsA[i]);
                foreach (Slig slig in Sligs)
                    totalAI += slig.AI_LEVEL;

                if (totalAI == Sligs.Count)//tutti gli slig hanno AI di basso livello
                {
                    Sligs.RemoveAt(0);
                }
                else
                {
                    foreach (Slig slig in Sligs)
                        if (slig.AI_LEVEL > 1)
                            slig.AI_LEVEL--;
                }
            }
        }

        //Incrementa la difficoltà del livello agendo sulle trappole(ObjectA:BOMBINNESCO)
        public void SetUPBombInnesco()
        {
            int bombInnNum = 0;
            int AllRange = 0;
            foreach (ObjectA bombInn in ObjectsA)
            {
                if (bombInn.NAME == "BOMBINNESCO")
                {
                    if (bombInn.RangeInnesco >= 3)
                    {
                        bombInn.RangeInnesco -= 2;
                    }
                }
            }
            foreach (ObjectA bombInn in ObjectsA)
            {
                if (bombInn.NAME == "BOMBINNESCO")
                {
                    bombInnNum++;
                    AllRange += bombInn.RangeInnesco;
                }
            }

            if (AllRange == bombInnNum)
            {
                int bombs = 0;
                Rectangle NewBomb = new Rectangle(19, 385, 19, 50);
                List<string> Colls = this.collision(NewBomb);


                for (int i = 19; i <= 572; i += 43)
                {
                    NewBomb.X = i;
                    Colls = this.collision(NewBomb);
                    if (Colls.Contains(COLLISIONS.BOMBINNESCO))
                    {
                        bombs++;
                    }
                    if (!Colls.Contains(COLLISIONS.BOMBINNESCO) & bombs > 0 & bombs < 3)
                    {
                        if (Colls.Count == 0 || Colls.Contains(COLLISIONS.HOISTSINISTRO) || Colls.Contains(COLLISIONS.HOISTDESTRO) || Colls.Contains(COLLISIONS.APPIGLIOSINISTRO) || Colls.Contains(COLLISIONS.APPIGLIODESTRO))
                        {
                            NewBomb = new Rectangle(NewBomb.X - 20, NewBomb.Y, 60, 50);
                            Collision bombColl = new Collision(COLLISIONS.BOMBINNESCO, NewBomb);
                            ObjectA Bomb = new ObjectA(game, "BOMBINNESCO", new Rectangle(NewBomb.X - 9, NewBomb.Y - 55, 70, 70), bombColl, this);
                            bombColl.OBJA = Bomb;

                            this.AddObjectA(Bomb);
                            i = 1000;
                        }
                        else
                        {
                            NewBomb.X = i - 43 * (bombs + 1);
                            Colls = this.collision(NewBomb);
                            if (Colls.Count == 0)
                            {
                                NewBomb = new Rectangle(NewBomb.X - 20, NewBomb.Y, 60, 50);
                                Collision bombColl = new Collision(COLLISIONS.BOMBINNESCO, NewBomb);
                                ObjectA Bomb = new ObjectA(game, "BOMBINNESCO", new Rectangle(NewBomb.X - 9, NewBomb.Y - 55, 70, 70), bombColl, this);
                                bombColl.OBJA = Bomb;

                                this.AddObjectA(Bomb);
                                i = 1000;
                            }
                        }
                    }
                }

                bombs = 0;
                NewBomb = new Rectangle(19, 185, 19, 50);
                Colls = this.collision(NewBomb);


                for (int i = 19; i <= 572; i += 43)
                {
                    NewBomb.X = i;
                    Colls = this.collision(NewBomb);
                    if (Colls.Contains(COLLISIONS.BOMBINNESCO))
                    {
                        bombs++;
                    }
                    if (!Colls.Contains(COLLISIONS.BOMBINNESCO) & bombs > 0 & bombs < 3)
                    {
                        if (Colls.Count == 0 || Colls.Contains(COLLISIONS.HOISTSINISTRO) || Colls.Contains(COLLISIONS.HOISTDESTRO) || Colls.Contains(COLLISIONS.APPIGLIOSINISTRO) || Colls.Contains(COLLISIONS.APPIGLIODESTRO))
                        {
                            NewBomb = new Rectangle(NewBomb.X - 20, NewBomb.Y, 60, 50);
                            Collision bombColl = new Collision(COLLISIONS.BOMBINNESCO, NewBomb);
                            ObjectA Bomb = new ObjectA(game, "BOMBINNESCO", new Rectangle(NewBomb.X - 9, NewBomb.Y - 55, 70, 70), bombColl, this);
                            bombColl.OBJA = Bomb;

                            this.AddObjectA(Bomb);
                            i = 1000;
                        }
                        else
                        {
                            NewBomb.X = i - 43 * (bombs + 1);
                            Colls = this.collision(NewBomb);
                            if (Colls.Count == 0)
                            {
                                NewBomb = new Rectangle(NewBomb.X - 20, NewBomb.Y, 60, 50);
                                Collision bombColl = new Collision(COLLISIONS.BOMBINNESCO, NewBomb);
                                ObjectA Bomb = new ObjectA(game, "BOMBINNESCO", new Rectangle(NewBomb.X - 9, NewBomb.Y - 55, 70, 70), bombColl, this);
                                bombColl.OBJA = Bomb;

                                this.AddObjectA(Bomb);
                                i = 1000;
                            }
                        }
                    }
                }
            }
        }

        //Incrementa la difficoltà del livello agendo sulle trappole(ObjectA:BOMB)
        public void SetUPBomb()
        {
            int bombs = 0;
            Rectangle NewBomb = new Rectangle(13, 385, 30, 50);
            List<string> Colls = this.collision(NewBomb);

            for (int i = 13; i <= 572; i += 43)
            {
                NewBomb.X = i;
                Colls = this.collision(NewBomb);
                if (Colls.Contains(COLLISIONS.BOMB))
                {
                    bombs++;
                }
                if (!Colls.Contains(COLLISIONS.BOMB) & bombs > 0 & bombs < 3)
                {
                    if (Colls.Count == 0)
                    {
                        Collision bombColl = new Collision(COLLISIONS.BOMB, NewBomb);
                        ObjectA Bomb = new ObjectA(game, "BOMB", new Rectangle(NewBomb.X - 6, NewBomb.Y - 40, 50, 50), bombColl, this);
                        bombColl.OBJA = Bomb;

                        this.AddObjectA(Bomb);
                        i = 1000;
                    }
                    else
                    {
                        NewBomb.X = i - 43 * (bombs + 1);
                        Colls = this.collision(NewBomb);
                        if (Colls.Count == 0)
                        {
                            Collision bombColl = new Collision(COLLISIONS.BOMB, NewBomb);
                            ObjectA Bomb = new ObjectA(game, "BOMB", new Rectangle(NewBomb.X - 6, NewBomb.Y - 40, 50, 50), bombColl, this);
                            bombColl.OBJA = Bomb;

                            this.AddObjectA(Bomb);
                            i = 1000;
                        }
                    }
                }
            }
            bombs = 0;
            NewBomb = new Rectangle(13, 185, 30, 50);
            Colls = this.collision(NewBomb);

            for (int i = 13; i <= 572; i += 43)
            {
                NewBomb.X = i;
                Colls = this.collision(NewBomb);
                if (Colls.Contains(COLLISIONS.BOMB))
                {
                    bombs++;
                }
                if (!Colls.Contains(COLLISIONS.BOMB) & bombs > 0 & bombs < 3)
                {
                    if (Colls.Count == 0)
                    {
                        Collision bombColl = new Collision(COLLISIONS.BOMB, NewBomb);
                        ObjectA Bomb = new ObjectA(game, "BOMB", new Rectangle(NewBomb.X - 6, NewBomb.Y - 40, 50, 50), bombColl, this);
                        bombColl.OBJA = Bomb;
                        this.AddObjectA(Bomb);
                        i = 1000;
                    }
                    else
                    {
                        NewBomb.X = i - 43 * (bombs + 1);
                        Colls = this.collision(NewBomb);
                        if (Colls.Count == 0)
                        {
                            Collision bombColl = new Collision(COLLISIONS.BOMB, NewBomb);
                            ObjectA Bomb = new ObjectA(game, "BOMB", new Rectangle(NewBomb.X - 6, NewBomb.Y - 40, 50, 50), bombColl, this);
                            bombColl.OBJA = Bomb;

                            this.AddObjectA(Bomb);
                            i = 1000;
                        }
                    }
                }
            }
        }

        //Decrementa la difficoltà del livello agendo sulle trappole(ObjectA:BOMB)
        public void SetDOWNBomb()
        {
            int bombs = 0;
            Rectangle NewBomb = new Rectangle(13, 385, 30, 50);
            List<string> Colls = this.collision(NewBomb);

            for (int i = 13; i <= 572; i += 43)
            {
                NewBomb.X = i;
                Colls = this.collision(NewBomb);
                if (Colls.Contains(COLLISIONS.BOMB))
                {
                    bombs++;
                }
                if (!Colls.Contains(COLLISIONS.BOMB) && bombs >= 2 && bombs <= 3)
                {
                    NewBomb.X = i - 43;
                    for (int o = 0; o < ObjectsA.Count; o++)
                    {
                        if (ObjectsA[o].COLLISION.REC.Intersects(NewBomb))
                        {
                            RemoveObjectA(ObjectsA[o]);
                        }
                    }
                }
            }
            bombs = 0;
            NewBomb = new Rectangle(13, 185, 30, 50);
            Colls = this.collision(NewBomb);
            for (int i = 13; i <= 572; i += 43)
            {
                NewBomb.X = i;
                Colls = this.collision(NewBomb);
                if (Colls.Contains(COLLISIONS.BOMB))
                {
                    bombs++;
                }
                if (!Colls.Contains(COLLISIONS.BOMB) && bombs >= 2 && bombs <= 3)
                {
                    NewBomb.X = i - 43;
                    for (int o = 0; o < ObjectsA.Count; o++)
                    {
                        if (ObjectsA[o].COLLISION.REC.Intersects(NewBomb))
                        {
                            RemoveObjectA(ObjectsA[o]);
                        }
                    }
                }
            }
        }

        //Assegna il grado di difficoltà al livello in base agli elementi presenti
        public void SetDifficult()
        {
            int diff = 0;

            foreach (Slig slig in this.Sligs)
            {
                if (slig.AI.CURRENT_STATE.name == "SLEEP")
                    diff += 2;
                if (slig.AI.CURRENT_STATE.name == "WAIT")
                    diff += 3;

                diff += slig.AI_LEVEL;
            }

            foreach (Mudokon mudokon in this.Mudokons)
                diff += 1;

            foreach (ObjectA objA in this.ObjectsA)
            {
                if (objA.NAME == "MATTATOIO")
                {
                    if (objA.objControl.ACTIVE)//& loop
                        diff++;
                    else
                        diff--;
                }

                if (objA.NAME == "BOTOLA")
                    diff--;

                if (objA.NAME == "BOMBINNESCO")
                {
                    List<string> Colls = this.collision(objA.COLLISION.REC);

                    if (Colls.Contains(COLLISIONS.HOISTSINISTRO) || Colls.Contains(COLLISIONS.HOISTDESTRO) || Colls.Contains(COLLISIONS.APPIGLIOSINISTRO) || Colls.Contains(COLLISIONS.APPIGLIODESTRO))
                    {
                        if (objA.RangeInnesco == 9)
                            diff += 1;
                        if (objA.RangeInnesco == 7)
                            diff += 2;
                        if (objA.RangeInnesco == 5)
                            diff += 3;
                        if (objA.RangeInnesco == 5)
                            diff += 4;
                        if (objA.RangeInnesco == 1)
                            diff += 5;
                    }
                    else
                    {
                        diff += 1;
                    }
                }

                if (objA.NAME == "BOMB")
                    diff++;
                if (objA.NAME == "ELECTRO")
                    diff++;
            }
            if (this.Sentinella)
                diff++;

            this.difficult = diff;
        }
    }


    //Definisce un elemento srutturale del livello, secondo il tipo, dimensione e posizione
    //[p.54,55]
    public class Collision
    {
        public string TYPE;
        public Rectangle REC;
        public ObjectA OBJA;
        public Level LINKEDLEVEL;

        public Collision(string Type, Rectangle Rec)
        {
            this.TYPE = Type;
            this.REC = Rec;

            if (TYPE == COLLISIONS.DOOR)
                LINKEDLEVEL = null;
        }
    }
    //Contiene i riferimenti a tutte le tipologie di elemento strutturale
    public class COLLISIONS
    {
        public const string GRAYAREA = "GRAYAREA";
        public const string BLACKAREA = "BLACKAREA";
        public const string APPIGLIODESTRO = "APPIGLIODESTRO";
        public const string APPIGLIOSINISTRO = "APPIGLIOSINISTRO";
        public const string BLOCCO = "BLOCCO";
        public const string HOISTDESTRO = "HOISTDESTRO";
        public const string HOISTSINISTRO = "HOISTSINISTRO";
        public const string GODOWN = "GODOWN";
        public const string LEVA = "LEVA";
        public const string BOMBINNESCO = "BOMBINNESCO";
        public const string BOMB = "BOMB";
        public const string ELECTRO = "ELECTRO";
        public const string MATTATOIO = "MATTATOIO";
        public const string BOTOLA = "BOTOLA";
        public const string GODOWND = "GODOWND";
        public const string SHOCK = "SHOCK";
        public const string PORTAL = "PORTAL";
        public const string DOOR = "DOOR";

        public COLLISIONS(){}
    }

}
